package com.mcxx.config;

import com.mcxx.common.exception.BizException;
import com.mcxx.util.Constant;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Aspect
@Component
public class AnnotationAspectOrder {

    @Pointcut("@annotation(CheckOrderUse)")
    public void annotationPointCut(){
    }


    @Before("annotationPointCut()")
    public void around(JoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = methodSignature.getMethod();

        CheckOrderUse annotation = method.getAnnotation(CheckOrderUse.class);

        String methods = proceedingJoinPoint.getTarget().getClass().getName() + "." + proceedingJoinPoint.getSignature().getName();
        System.out.println("注解式拦截:" + methods);

        String check = check(proceedingJoinPoint, annotation,false);
        if(StringUtils.isEmpty(check)){

        }else{
            throw new BizException("-1", check);
        }
    }

    @After("annotationPointCut()")
    public void after(JoinPoint jp){
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        Method method = methodSignature.getMethod();

        CheckOrderUse annotation = method.getAnnotation(CheckOrderUse.class);
        check(jp, annotation,true);
    }

    @AfterThrowing(pointcut="annotationPointCut()", throwing="e")
    public void afterThrowing(JoinPoint jp,RuntimeException e){
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        Method method = methodSignature.getMethod();

        CheckOrderUse annotation = method.getAnnotation(CheckOrderUse.class);
        check(jp, annotation,true);
    }

    private String check(JoinPoint proceedingJoinPoint,CheckOrderUse annotation,boolean isExce){
        String type = annotation.type();
        int value = annotation.value();
        List<String> list = new ArrayList<>();
        Object arg = proceedingJoinPoint.getArgs()[value];
        try {
            switch (type){
                case "String":
                    String s = arg.toString();
                    list.add(s);
                    break;
                case "Strings":
                    String ss = arg.toString();
                    list.addAll(Stream.of(ss.split(",")).collect(Collectors.toList()));
                    break;
                case "array":
                    String[] ssa = (String[]) arg;
                    list.addAll(Stream.of(ssa).collect(Collectors.toList()));
                    break;
                case "lists":
                    List<String> ls = (List<String>) proceedingJoinPoint.getArgs()[value];
                    list.addAll(ls);
                    break;
                case "listo":
                    List<Object> lo = Collections.singletonList(arg);
                    for(Object o : lo){
                        Class<?> aClass = o.getClass();
                        Object object =  aClass.newInstance();
                        Field field = aClass.getDeclaredField("orderId");
                        String firstLetter=field.getName().substring(0,1).toUpperCase();
                        String getMethodName="get"+firstLetter+field.getName().substring(1);
                        Method getMethod=aClass.getMethod(getMethodName,new Class[]{});
                        Object orderId = getMethod.invoke(object,new Object[]{});
                        if(null != orderId){
                            list.add(orderId.toString());
                        }
                    }
                    break;
                case "object":
                    Class<?> aClass = arg.getClass();

                    Field field = aClass.getDeclaredField("orderId");
                    String firstLetter=field.getName().substring(0,1).toUpperCase();
                    String getMethodName="get"+firstLetter+field.getName().substring(1);
                    Method getMethod=aClass.getMethod(getMethodName,new Class[]{});
                    Object orderId = getMethod.invoke(arg,new Object[]{});
                    if(null != orderId){
                        list.add(orderId.toString());
                    }
                    break;
            }

            if(CollectionUtils.isNotEmpty(list)){
                if(isExce){
                    for(String s : list){

                        if(Constant.orderUseMap.containsKey(s)){
                            Constant.orderUseMap.remove(s);
                        }
                    }
                }else{
                    int i = 1;
                    StringBuffer sb = new StringBuffer();
                    for(String s : list){

                        if(Constant.orderUseMap.containsKey(s)){
                            sb.append("选中的业务数据第").append(i)
                                    .append("条正在执行")
                                    .append(Constant.orderUseMap.get(s))
                                    .append("操作，请稍后重试")
                                    .append(",");


                        }else{
                            Constant.orderUseMap.put(s,annotation.notes());
                        }
                        i++;
                    }
                    if(StringUtils.isNotBlank(sb.toString())){
                        return sb.toString();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
}
